﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace MediaData
{
    public class TVScanner : MediaItemScanner
    {
        public bool SortSeasons { get; set; }
        public string SeasonString { get; set; }
        public TVScanner(string type)
            : base(type)
        {
            SeasonString = "Season {0}";
        }

        public override void Scan(MediaRoot root, Predicate<MediaItem> exists, Action<MediaItem> mediaAdded)
        {

            foreach (var titleDir in Directory.GetDirectories(Path.Combine(root.Path, this.Type)))
            {
                string titleName = Path.GetFileName(titleDir);
                if (titleName.StartsWith("."))
                    continue;

                foreach (string file in Directory.GetFiles(titleDir, "*.*", SearchOption.AllDirectories))
                {
                    MediaType mediaType = this.GetType(Path.GetFileName(file));
                    if (mediaType != MediaType.Video && mediaType != MediaType.DiscImage)
                        continue;


                    MediaItem v = new MediaItem(root.Volume, file);

                    if (exists == null || !exists(v))
                    {
                        string rest = ParseTVShowFilename(v, file);

                        v.Title = titleName;
                        v.Type = this.Type;

                        if (v.Episode > 0 && v.Season > 0 && SortSeasons)
                        {
                            string newPath = MoveTVShow(titleDir, file, v, rest);
                            if (newPath != file)
                                v.Path = newPath;
                        }

                        mediaAdded(v);
                    }
                }
            }

        }
        protected string MoveTVShow(string showDir, string path, MediaItem v, string tail)
        {
            //string tail = v.comment;// Regex.Replace(v.comment, @"(?i)[^A-Z0-9 \+=']+", " ").Trim().Replace(' ', '.').ToLower();

            Match m = Regex.Match(tail, @"(?i)^[_\-\. ]*(.*?)[_\-\. ]*$");
            if (m.Success)
                tail = m.Groups[1].Value;
            if (tail.Length > 0) tail = "." + tail.Trim();

            string lastEpisode = v.LastEpisode > v.Episode ? "-" + v.LastEpisode.ToString().PadLeft(2, '0') : "";

            string newName = v.Title + "." + "s" + v.Season.ToString().PadLeft(2, '0') + "e" + v.Episode.ToString().PadLeft(2, '0') + lastEpisode + tail + Path.GetExtension(path);
            newName = Regex.Replace(newName, @"\s+", ".");
            string newPath = showDir + Path.DirectorySeparatorChar + string.Format(SeasonString, v.Season) + Path.DirectorySeparatorChar + newName;
            string newRelatedPath;
            if (path.ToLower().Equals(newPath.ToLower()))
                return path;

           
            try
            {
                if (File.Exists(newPath))
                    newPath = showDir + Path.DirectorySeparatorChar + newName;

                if (!File.Exists(newPath))
                {
                    if (!Directory.Exists(Path.GetDirectoryName(newPath)))
                        Directory.CreateDirectory(Path.GetDirectoryName(newPath));

                    File.Move(path, newPath);
                    foreach (string relatedPath in MediaUtil.RelatedFiles(path))
                    {
                        if (GetType(relatedPath) != MediaType.Unknown)
                            continue;

                        newRelatedPath = Path.ChangeExtension(newPath, Path.GetExtension(relatedPath));
                        if (!File.Exists(newRelatedPath))
                            File.Move(relatedPath, newRelatedPath);
                    }
                }
            }
            catch
            {
                return path;
            }
            return newPath;
        }
        public static string ParseTVShowFilename(MediaItem video, string file)
        {
            string rest = "";
            Regex[] patnr = {
                new Regex(@"(?i)(?:^.*?[^a-z0-9]|^)s?(\d{1,2})[a-z]+(\d{1,2})[\-_. ](?:ep|[a-z])?(\d{1,2})((?:[^a-z0-9].*?|\.)\w{3,})$"),
                new Regex(@"(?i)(?:^.*?[^a-z0-9]|^)s?(\d{1,2})[a-z]+(\d{1,2})((?:[^a-z0-9].*?|\.)\w{3,})$"),
                new Regex(@"(?i)(?:^.*?[^a-z0-9]|^)(\d{3})((?:[^a-z0-9](\D)*?|\.)\w{3,})$"),
                new Regex(@"(?i)(?:^.*?[^a-z0-9]|^)(\d{3})((?:[^a-z0-9].*?|\.)\w{3,})$"),
                new Regex(@"(?i)(?:^.*?[^a-z0-9]|^)s?(\d{1,2})[^a-z0-9].*?(?:e|d|ep)(\d{1,2})((?:[^a-z0-9].*?|\.)\w{3,})$"),
                new Regex(@"(?i)(?:^.*?[^a-z0-9]|^)[a-z]+(\d{1,2})((?:[^a-z0-9].*?|\.)\w{3,})$")
                            };
            for (int i = 0; i < patnr.Length; i++)
            {
                Match m = patnr[i].Match(Path.GetFileName(file));
                if (m.Success)
                {
                    switch (i)
                    {
                        case 0:
                            video.Season = Int32.Parse(m.Groups[1].Value);
                            video.Episode = Int32.Parse(m.Groups[2].Value);
                            video.LastEpisode = Int32.Parse(m.Groups[3].Value);
                            if (video.LastEpisode < video.Episode)
                                video.LastEpisode = video.Episode;
                            rest = Path.GetFileNameWithoutExtension(m.Groups[4].ToString());
                            break;
                        case 1:
                        case 4:
                            video.Season = Int32.Parse(m.Groups[1].Value);
                            video.LastEpisode = video.Episode = Int32.Parse(m.Groups[2].Value);
                            rest = Path.GetFileNameWithoutExtension(m.Groups[3].ToString());
                            break;
                        case 2:
                        case 3:
                            video.Season = Int32.Parse(m.Groups[1].Value.Substring(0, 1));
                            video.LastEpisode = video.Episode = Int32.Parse(m.Groups[1].Value.Substring(1, 2));
                            rest = Path.GetFileNameWithoutExtension(m.Groups[2].ToString());
                            break;
                        case 5:
                            video.Season = 0;
                            video.LastEpisode = video.Episode = Int32.Parse(m.Groups[1].Value);
                            rest = Path.GetFileNameWithoutExtension(m.Groups[2].ToString());
                            break;
                    }
                    return rest;
                }
            }
            return rest;
        }

    }
}
